package org.cybzacg.convert.converters.date;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.constants.DateFormats;
import org.cybzacg.convert.constants.DateTimeDefaults;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;

/**
 * Date转换器
 * 专门处理java.util.Date类型的转换
 *
 * @author cybzacg.blog
 * @version 4.0
 * @since 3.0
 */
@Slf4j
@Converter(name = "DateConverter", priority = ConversionPriority.MEDIUM_HIGH, description = "Date类型转换器，处理各种类型到java.util.Date的转换", version = "4.0", author = "cybzacg.blog", supportedTypes = {
        Date.class }, tags = { "date", "time", "conversion" })
public class DateConverter extends AbstractDateTimeConverter<Date> {

    public DateConverter() {
        super(Date.class, ConversionPriority.MEDIUM_HIGH);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.DATE;
    }

    @Override
    protected Date parseFromString(String str, DateTimeFormatter formatter) throws DateTimeParseException {
        // 尝试解析为各种java.time类型，然后转换为Date
        try {
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(str, formatter);
            return Date.from(zonedDateTime.toInstant());
        } catch (DateTimeParseException e) {
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(str, formatter);
                return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
            } catch (DateTimeParseException ex) {
                try {
                    LocalDate localDate = LocalDate.parse(str, formatter);
                    return Date.from(localDate.atStartOfDay(DEFAULT_ZONE_ID).toInstant());
                } catch (DateTimeParseException ex2) {
                    // 最后尝试LocalTime
                    LocalTime localTime = LocalTime.parse(str, formatter);
                    return Date.from(LocalDate.now().atTime(localTime).atZone(DEFAULT_ZONE_ID).toInstant());
                }
            }
        }
    }

    @Override
    protected Date convertFromInstant(Instant instant, ConversionContext context) {
        return Date.from(instant);
    }

    @Override
    protected String[] getSupportedPatterns() {
        // 合并所有格式：时区、日期时间、日期、时间
        String[] timezonePatterns = DateFormats.TIMEZONE_FORMAT_PATTERNS;
        String[] datetimePatterns = DateFormats.DATETIME_FORMAT_PATTERNS;
        String[] datePatterns = DateFormats.DATE_FORMAT_PATTERNS;
        String[] timePatterns = DateFormats.TIME_FORMAT_PATTERNS;

        int totalLength = timezonePatterns.length + datetimePatterns.length +
                datePatterns.length + timePatterns.length;
        String[] allPatterns = new String[totalLength];

        int pos = 0;
        System.arraycopy(timezonePatterns, 0, allPatterns, pos, timezonePatterns.length);
        pos += timezonePatterns.length;
        System.arraycopy(datetimePatterns, 0, allPatterns, pos, datetimePatterns.length);
        pos += datetimePatterns.length;
        System.arraycopy(datePatterns, 0, allPatterns, pos, datePatterns.length);
        pos += datePatterns.length;
        System.arraycopy(timePatterns, 0, allPatterns, pos, timePatterns.length);

        return allPatterns;
    }

    @Override
    protected Date convertFromOtherDateTime(Object source, ConversionContext context) {
        // LocalDateTime转换
        if (source instanceof LocalDateTime localDateTime) {
            return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
        }

        // ZonedDateTime转换
        if (source instanceof ZonedDateTime zonedDateTime) {
            return Date.from(zonedDateTime.toInstant());
        }

        // LocalDate转换
        if (source instanceof LocalDate localDate) {
            return Date.from(localDate.atStartOfDay(DEFAULT_ZONE_ID).toInstant());
        }

        // LocalTime转换（今天的该时间）
        if (source instanceof LocalTime localTime) {
            return Date.from(LocalDate.now().atTime(localTime).atZone(DEFAULT_ZONE_ID).toInstant());
        }

        // Year转换
        if (source instanceof Year year) {
            return Date.from(year.atDay(1).atStartOfDay(DEFAULT_ZONE_ID).toInstant());
        }

        // YearMonth转换
        if (source instanceof YearMonth yearMonth) {
            return Date.from(yearMonth.atDay(1).atStartOfDay(DEFAULT_ZONE_ID).toInstant());
        }

        return null;
    }

    @Override
    protected Date getDefaultValue() {
        return DateTimeDefaults.DATE_DEFAULT;
    }
}
